import config from '../config/index.js'
import { WebSocketServer } from 'ws'
import https from 'https'
import fs from 'fs'
import redisManager from './redisManager.js'
import connectionManager from './connectionManager.js'
import messageHandler from './messageHandler.js'
import logger from './logger.js'
import { REDIS_CHANNELS, WS_COMMANDS, CLOSE_CODES } from '../constants/index.js'

/**
 * WebRTC 信令服务器
 * 负责管理 WebSocket 连接和消息路由
 */
class WebRTCSignalServer {
  constructor() {
    this.wssServer = null
    this.connectionManager = new connectionManager()
    this.messageHandler = new messageHandler(this.connectionManager)
    this.setupRedisMessageHandling()
  }

  /**
   * 设置 Redis 消息处理
   */
  setupRedisMessageHandling() {
    const redisSub = redisManager.getSubscribeClient()

    redisSub.on('message', (channel, message) => {
      try {
        const data = JSON.parse(message)
    
        if (channel === REDIS_CHANNELS.BROADCAST) {
          this.handleBroadcastMessage(data)
        } else if (channel === REDIS_CHANNELS.RELAY) {
          this.handleRelayMessage(data)
        }
      } catch (error) {
        logger.error('Redis 消息处理失败:', error)
      }
    })
  }

  /**
   * 处理广播消息
   */
  handleBroadcastMessage(data) {
    const { connId, payload } = data
    if (payload.cmd === WS_COMMANDS.ADMIN_BROADCAST) {
      logger.info('接收到广播消息', data)
    } else {
      const conn = this.connectionManager.getConnection(connId)
      if (!conn) return

      if (payload.cmd === WS_COMMANDS.ADMIN_KICK) {
        try {
          conn.close(CLOSE_CODES.DUPLICATE_CONNECTION, 'duplicate connection')
        } catch (error) {
          logger.debug('关闭连接时出错:', error.message)
        }
      } else {
        logger.message('发送消息：', connId, JSON.stringify(payload))
        this.connectionManager.safeSend(conn, payload)
      }
    }
  }

  /**
   * 处理中继消息
   */
  handleRelayMessage(data) {
    const { connId, payload } = data
    const conn = this.connectionManager.getConnection(connId)
    
    if (conn) {
      this.connectionManager.safeSend(conn, payload)
    }
  }

  /**
   * 启动 WebSocket 服务器
   */
  run() {
    const wssPort = config.websocket.port
    
    if (config.websocket.useSSL) {
      this.startSecureServer(wssPort)
    } else {
      this.startInsecureServer(wssPort)
    }
    
    this.setupServerEvents()
    this.connectionManager.startHeartbeat()
  }

  /**
   * 启动安全服务器 (WSS)
   */
  startSecureServer(port) {
    logger.info('启动WSS服务器（生产环境）')
    
    try {
        const sslKey = fs.readFileSync(config.websocket.ssl.key)
        const sslCert = fs.readFileSync(config.websocket.ssl.cert)
        const sslCa = fs.readFileSync(config.websocket.ssl.ca)
        
      const tlsOptions = { key: sslKey, cert: sslCert, ca: sslCa }
        const signalHttpsServer = https.createServer(tlsOptions)
        this.wssServer = new WebSocketServer({ server: signalHttpsServer })
        
      signalHttpsServer.listen(port, '0.0.0.0', () => {
        logger.info(`WSS服务器运行在端口 ${port}`)
        })
      } catch (error) {
      logger.error('SSL证书文件读取失败:', error)
      logger.info('回退到WS模式')
      this.startInsecureServer(port)
    }
  }

  /**
   * 启动非安全服务器 (WS)
   */
  startInsecureServer(port) {
    logger.info('启动WS服务器（开发环境）')
    this.wssServer = new WebSocketServer({ port })
  }

  /**
   * 设置服务器事件监听
   */
  setupServerEvents() {
    const wssPort = config.websocket.port
    
    this.wssServer.on('listening', () => {
      const protocol = config.websocket.useSSL ? 'WSS' : 'WS'
      logger.info(`${protocol}服务器运行在端口 ${wssPort}`)
    })

    this.wssServer.on('connection', async (conn, req) => {
      await this.handleNewConnection(conn, req)
    })
  }

  /**
   * 处理新连接
   */
  async handleNewConnection(conn, req) {
    try {
      const connectionInfo = await this.connectionManager.handleNewConnection(conn, req)
      if (!connectionInfo) return

      const { connId, roomId, uid } = connectionInfo
      logger.connection(`客户端已连接: ${uid} (房间: ${roomId})`, connId)

      // 设置消息处理
      conn.on('message', async (message) => {
        logger.message(`接收到消息：${message}`, connId)
        // 收到任何消息都视为活跃
        conn.isAlive = true
        conn.lastActiveAt = Date.now()
        
        await this.messageHandler.handleMessage(message, conn, connId)
      })

      // 设置连接关闭处理
      conn.on('close', async () => {
        await this.connectionManager.handleConnectionClose(connId)
      })

    } catch (error) {
      logger.error('处理新连接失败:', error)
    }
  }

  /**
   * 停止服务器
   */
  stop() {
    this.connectionManager.stopHeartbeat()
    if (this.wssServer) {
      this.wssServer.close()
    }
  }
}

// 创建 WebRTC 信令服务器实例
const ws = new WebRTCSignalServer()

export default ws